home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Date.php < prev    next >
PHP Script  |  2004-10-01  |  37KB  |  1,225 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Baba Buehler <baba@babaz.com>                               |
  17. // |          Pierre-Alain Joye <pajoye@php.net>                          |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Date.php,v 1.28 2004/05/16 13:11:07 pajoye Exp $
  21.  
  22. /**@#+
  23.  * Include supporting classes
  24.  */
  25. require_once 'Date/TimeZone.php';
  26. require_once 'Date/Calc.php';
  27. require_once 'Date/Span.php';
  28. /**@#-*/
  29.  
  30. /**@#+
  31.  * Output formats.  Pass this to getDate().
  32.  */
  33. /**
  34.  * "YYYY-MM-DD HH:MM:SS"
  35.  */
  36. define('DATE_FORMAT_ISO', 1);
  37. /**
  38.  * "YYYYMMSSTHHMMSS(Z|(+/-)HHMM)?"
  39.  */
  40. define('DATE_FORMAT_ISO_BASIC', 2);
  41. /**
  42.  * "YYYY-MM-SSTHH:MM:SS(Z|(+/-)HH:MM)?"
  43.  */
  44. define('DATE_FORMAT_ISO_EXTENDED', 3);
  45. /**
  46.  * "YYYY-MM-SSTHH:MM:SS(.S*)?(Z|(+/-)HH:MM)?"
  47.  */
  48. define('DATE_FORMAT_ISO_EXTENDED_MICROTIME', 6);
  49. /**
  50.  * "YYYYMMDDHHMMSS"
  51.  */
  52. define('DATE_FORMAT_TIMESTAMP', 4);
  53. /**
  54.  * long int, seconds since the unix epoch
  55.  */
  56. define('DATE_FORMAT_UNIXTIME', 5);
  57. /**@#-*/
  58.  
  59. /**
  60.  * Generic date handling class for PEAR.
  61.  *
  62.  * Generic date handling class for PEAR.  Attempts to be time zone aware
  63.  * through the Date::TimeZone class.  Supports several operations from
  64.  * Date::Calc on Date objects.
  65.  *
  66.  * @author Baba Buehler <baba@babaz.com>
  67.  * @package Date
  68.  * @access public
  69.  */
  70. class Date
  71. {
  72.     /**
  73.      * the year
  74.      * @var int
  75.      */
  76.     var $year;
  77.     /**
  78.      * the month
  79.      * @var int
  80.      */
  81.     var $month;
  82.     /**
  83.      * the day
  84.      * @var int
  85.      */
  86.     var $day;
  87.     /**
  88.      * the hour
  89.      * @var int
  90.      */
  91.     var $hour;
  92.     /**
  93.      * the minute
  94.      * @var int
  95.      */
  96.     var $minute;
  97.     /**
  98.      * the second
  99.      * @var int
  100.      */
  101.     var $second;
  102.     /**
  103.      * the parts of a second
  104.      * @var float
  105.      */
  106.     var $partsecond;
  107.     /**
  108.      * timezone for this date
  109.      * @var object Date_TimeZone
  110.      */
  111.     var $tz;
  112.  
  113.  
  114.     /**
  115.      * Constructor
  116.      *
  117.      * Creates a new Date Object initialized to the current date/time in the
  118.      * system-default timezone by default.  A date optionally
  119.      * passed in may be in the ISO 8601, TIMESTAMP or UNIXTIME format,
  120.      * or another Date object.  If no date is passed, the current date/time
  121.      * is used.
  122.      *
  123.      * @access public
  124.      * @see setDate()
  125.      * @param mixed $date optional - date/time to initialize
  126.      * @return object Date the new Date object
  127.      */
  128.     function Date($date = null)
  129.     {
  130.         $this->tz = Date_TimeZone::getDefault();
  131.         if (is_null($date)) {
  132.             $this->setDate(date("Y-m-d H:i:s"));
  133.         } elseif (is_a($date, 'Date')) {
  134.             $this->copy($date);
  135.         } else {
  136.             $this->setDate($date);
  137.         }
  138.     }
  139.  
  140.     /**
  141.      * Set the fields of a Date object based on the input date and format
  142.      *
  143.      * Set the fields of a Date object based on the input date and format,
  144.      * which is specified by the DATE_FORMAT_* constants.
  145.      *
  146.      * @access public
  147.      * @param string $date input date
  148.      * @param int $format Optional format constant (DATE_FORMAT_*) of the input date.
  149.      *                    This parameter isn't really needed anymore, but you could
  150.      *                    use it to force DATE_FORMAT_UNIXTIME.
  151.      */
  152.     function setDate($date, $format = DATE_FORMAT_ISO)
  153.     {
  154.  
  155.         if (
  156.             preg_match('/^(\d{4})-?(\d{2})-?(\d{2})([T\s]?(\d{2}):?(\d{2}):?(\d{2})(\.\d+)?(Z|[\+\-]\d{2}:?\d{2})?)?$/i', $date, $regs)
  157.             && $format != DATE_FORMAT_UNIXTIME) {
  158.             // DATE_FORMAT_ISO, ISO_BASIC, ISO_EXTENDED, and TIMESTAMP
  159.             // These formats are extremely close to each other.  This regex
  160.             // is very loose and accepts almost any butchered format you could
  161.             // throw at it.  e.g. 2003-10-07 19:45:15 and 2003-10071945:15
  162.             // are the same thing in the eyes of this regex, even though the
  163.             // latter is not a valid ISO 8601 date.
  164.             $this->year       = $regs[1];
  165.             $this->month      = $regs[2];
  166.             $this->day        = $regs[3];
  167.             $this->hour       = isset($regs[5])?$regs[5]:0;
  168.             $this->minute     = isset($regs[6])?$regs[6]:0;
  169.             $this->second     = isset($regs[7])?$regs[7]:0;
  170.             $this->partsecond = isset($regs[8])?(float)$regs[8]:(float)0;
  171.  
  172.             // if an offset is defined, convert time to UTC
  173.             // Date currently can't set a timezone only by offset,
  174.             // so it has to store it as UTC
  175.             if (isset($regs[9])) {
  176.                 $this->toUTCbyOffset($regs[9]);
  177.             }
  178.         } elseif (is_numeric($date)) {
  179.             // UNIXTIME
  180.             $this->setDate(date("Y-m-d H:i:s", $date));
  181.         } else {
  182.             // unknown format
  183.             $this->year       = 0;
  184.             $this->month      = 1;
  185.             $this->day        = 1;
  186.             $this->hour       = 0;
  187.             $this->minute     = 0;
  188.             $this->second     = 0;
  189.             $this->partsecond = (float)0;
  190.         }
  191.     }
  192.  
  193.     /**
  194.      * Get a string (or other) representation of this date
  195.      *
  196.      * Get a string (or other) representation of this date in the
  197.      * format specified by the DATE_FORMAT_* constants.
  198.      *
  199.      * @access public
  200.      * @param int $format format constant (DATE_FORMAT_*) of the output date
  201.      * @return string the date in the requested format
  202.      */
  203.     function getDate($format = DATE_FORMAT_ISO)
  204.     {
  205.         switch ($format) {
  206.         case DATE_FORMAT_ISO:
  207.             return $this->format("%Y-%m-%d %T");
  208.             break;
  209.         case DATE_FORMAT_ISO_BASIC:
  210.             $format = "%Y%m%dT%H%M%S";
  211.             if ($this->tz->getID() == 'UTC') {
  212.                 $format .= "Z";
  213.             }
  214.             return $this->format($format);
  215.             break;
  216.         case DATE_FORMAT_ISO_EXTENDED:
  217.             $format = "%Y-%m-%dT%H:%M:%S";
  218.             if ($this->tz->getID() == 'UTC') {
  219.                 $format .= "Z";
  220.             }
  221.             return $this->format($format);
  222.             break;
  223.         case DATE_FORMAT_ISO_EXTENDED_MICROTIME:
  224.             $format = "%Y-%m-%dT%H:%M:%s";
  225.             if ($this->tz->getID() == 'UTC') {
  226.                 $format .= "Z";
  227.             }
  228.             return $this->format($format);
  229.             break;
  230.         case DATE_FORMAT_TIMESTAMP:
  231.             return $this->format("%Y%m%d%H%M%S");
  232.             break;
  233.         case DATE_FORMAT_UNIXTIME:
  234.             return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
  235.             break;
  236.         }
  237.     }
  238.  
  239.     /**
  240.      * Copy values from another Date object
  241.      *
  242.      * Makes this Date a copy of another Date object.
  243.      *
  244.      * @access public
  245.      * @param object Date $date Date to copy from
  246.      */
  247.     function copy($date)
  248.     {
  249.         $this->year = $date->year;
  250.         $this->month = $date->month;
  251.         $this->day = $date->day;
  252.         $this->hour = $date->hour;
  253.         $this->minute = $date->minute;
  254.         $this->second = $date->second;
  255.         $this->tz = $date->tz;
  256.     }
  257.  
  258.     /**
  259.      *  Date pretty printing, similar to strftime()
  260.      *
  261.      *  Formats the date in the given format, much like
  262.      *  strftime().  Most strftime() options are supported.<br><br>
  263.      *
  264.      *  formatting options:<br><br>
  265.      *
  266.      *  <code>%a  </code>  abbreviated weekday name (Sun, Mon, Tue) <br>
  267.      *  <code>%A  </code>  full weekday name (Sunday, Monday, Tuesday) <br>
  268.      *  <code>%b  </code>  abbreviated month name (Jan, Feb, Mar) <br>
  269.      *  <code>%B  </code>  full month name (January, February, March) <br>
  270.      *  <code>%C  </code>  century number (the year divided by 100 and truncated to an integer, range 00 to 99) <br>
  271.      *  <code>%d  </code>  day of month (range 00 to 31) <br>
  272.      *  <code>%D  </code>  same as "%m/%d/%y" <br>
  273.      *  <code>%e  </code>  day of month, single digit (range 0 to 31) <br>
  274.      *  <code>%E  </code>  number of days since unspecified epoch (integer, Date_Calc::dateToDays()) <br>
  275.      *  <code>%H  </code>  hour as decimal number (00 to 23) <br>
  276.      *  <code>%I  </code>  hour as decimal number on 12-hour clock (01 to 12) <br>
  277.      *  <code>%j  </code>  day of year (range 001 to 366) <br>
  278.      *  <code>%m  </code>  month as decimal number (range 01 to 12) <br>
  279.      *  <code>%M  </code>  minute as a decimal number (00 to 59) <br>
  280.      *  <code>%n  </code>  newline character (\n) <br>
  281.      *  <code>%O  </code>  dst-corrected timezone offset expressed as "+/-HH:MM" <br>
  282.      *  <code>%o  </code>  raw timezone offset expressed as "+/-HH:MM" <br>
  283.      *  <code>%p  </code>  either 'am' or 'pm' depending on the time <br>
  284.      *  <code>%P  </code>  either 'AM' or 'PM' depending on the time <br>
  285.      *  <code>%r  </code>  time in am/pm notation, same as "%I:%M:%S %p" <br>
  286.      *  <code>%R  </code>  time in 24-hour notation, same as "%H:%M" <br>
  287.      *  <code>%s  </code>  seconds including the decimal representation smaller than one second <br>
  288.      *  <code>%S  </code>  seconds as a decimal number (00 to 59) <br>
  289.      *  <code>%t  </code>  tab character (\t) <br>
  290.      *  <code>%T  </code>  current time, same as "%H:%M:%S" <br>
  291.      *  <code>%w  </code>  weekday as decimal (0 = Sunday) <br>
  292.      *  <code>%U  </code>  week number of current year, first sunday as first week <br>
  293.      *  <code>%y  </code>  year as decimal (range 00 to 99) <br>
  294.      *  <code>%Y  </code>  year as decimal including century (range 0000 to 9999) <br>
  295.      *  <code>%%  </code>  literal '%' <br>
  296.      * <br>
  297.      *
  298.      * @access public
  299.      * @param string format the format string for returned date/time
  300.      * @return string date/time in given format
  301.      */
  302.     function format($format)
  303.     {
  304.         $output = "";
  305.  
  306.         for($strpos = 0; $strpos < strlen($format); $strpos++) {
  307.             $char = substr($format,$strpos,1);
  308.             if ($char == "%") {
  309.                 $nextchar = substr($format,$strpos + 1,1);
  310.                 switch ($nextchar) {
  311.                 case "a":
  312.                     $output .= Date_Calc::getWeekdayAbbrname($this->day,$this->month,$this->year);
  313.                     break;
  314.                 case "A":
  315.                     $output .= Date_Calc::getWeekdayFullname($this->day,$this->month,$this->year);
  316.                     break;
  317.                 case "b":
  318.                     $output .= Date_Calc::getMonthAbbrname($this->month);
  319.                     break;
  320.                 case "B":
  321.                     $output .= Date_Calc::getMonthFullname($this->month);
  322.                     break;
  323.                 case "C":
  324.                     $output .= sprintf("%02d",intval($this->year/100));
  325.                     break;
  326.                 case "d":
  327.                     $output .= sprintf("%02d",$this->day);
  328.                     break;
  329.                 case "D":
  330.                     $output .= sprintf("%02d/%02d/%02d",$this->month,$this->day,$this->year);
  331.                     break;
  332.                 case "e":
  333.                     $output .= $this->day * 1; // get rid of leading zero
  334.                     break;
  335.                 case "E":
  336.                     $output .= Date_Calc::dateToDays($this->day,$this->month,$this->year);
  337.                     break;
  338.                 case "H":
  339.                     $output .= sprintf("%02d", $this->hour);
  340.                     break;
  341.                 case "I":
  342.                     $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
  343.                     $output .= sprintf("%02d", $hour==0 ? 12 : $hour);
  344.                     break;
  345.                 case "j":
  346.                     $output .= Date_Calc::julianDate($this->day,$this->month,$this->year);
  347.                     break;
  348.                 case "m":
  349.                     $output .= sprintf("%02d",$this->month);
  350.                     break;
  351.                 case "M":
  352.                     $output .= sprintf("%02d",$this->minute);
  353.                     break;
  354.                 case "n":
  355.                     $output .= "\n";
  356.                     break;
  357.                 case "O":
  358.                     $offms = $this->tz->getOffset($this);
  359.                     $direction = $offms >= 0 ? "+" : "-";
  360.                     $offmins = abs($offms) / 1000 / 60;
  361.                     $hours = $offmins / 60;
  362.                     $minutes = $offmins % 60;
  363.                     $output .= sprintf("%s%02d:%02d", $direction, $hours, $minutes);
  364.                     break;
  365.                 case "o":
  366.                     $offms = $this->tz->getRawOffset($this);
  367.                     $direction = $offms >= 0 ? "+" : "-";
  368.                     $offmins = abs($offms) / 1000 / 60;
  369.                     $hours = $offmins / 60;
  370.                     $minutes = $offmins % 60;
  371.                     $output .= sprintf("%s%02d:%02d", $direction, $hours, $minutes);
  372.                     break;
  373.                 case "p":
  374.                     $output .= $this->hour >= 12 ? "pm" : "am";
  375.                     break;
  376.                 case "P":
  377.                     $output .= $this->hour >= 12 ? "PM" : "AM";
  378.                     break;
  379.                 case "r":
  380.                     $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
  381.                     $output .= sprintf("%02d:%02d:%02d %s", $hour==0 ?  12 : $hour, $this->minute, $this->second, $this->hour >= 12 ? "PM" : "AM");
  382.                     break;
  383.                 case "R":
  384.                     $output .= sprintf("%02d:%02d", $this->hour, $this->minute);
  385.                     break;
  386.                 case "s":
  387.                     $output .= sprintf("%02f", (float)((float)$this->second + $this->partsecond));
  388.                     break;
  389.                 case "S":
  390.                     $output .= sprintf("%02d", $this->second);
  391.                     break;
  392.                 case "t":
  393.                     $output .= "\t";
  394.                     break;
  395.                 case "T":
  396.                     $output .= sprintf("%02d:%02d:%02d", $this->hour, $this->minute, $this->second);
  397.                     break;
  398.                 case "w":
  399.                     $output .= Date_Calc::dayOfWeek($this->day,$this->month,$this->year);
  400.                     break;
  401.                 case "U":
  402.                     $output .= Date_Calc::weekOfYear($this->day,$this->month,$this->year);
  403.                     break;
  404.                 case "y":
  405.                     $output .= substr($this->year,2,2);
  406.                     break;
  407.                 case "Y":
  408.                     $output .= $this->year;
  409.                     break;
  410.                 case "Z":
  411.                     $output .= $this->tz->inDaylightTime($this) ? $this->tz->getDSTShortName() : $this->tz->getShortName();
  412.                     break;
  413.                 case "%":
  414.                     $output .= "%";
  415.                     break;
  416.                 default:
  417.                     $output .= $char.$nextchar;
  418.                 }
  419.                 $strpos++;
  420.             } else {
  421.                 $output .= $char;
  422.             }
  423.         }
  424.         return $output;
  425.  
  426.     }
  427.  
  428.     /**
  429.      * Get this date/time in Unix time() format
  430.      *
  431.      * Get a representation of this date in Unix time() format.  This may only be
  432.      * valid for dates from 1970 to ~2038.
  433.      *
  434.      * @access public
  435.      * @return int number of seconds since the unix epoch
  436.      */
  437.     function getTime()
  438.     {
  439.         return $this->getDate(DATE_FORMAT_UNIXTIME);
  440.     }
  441.  
  442.     /**
  443.      * Sets the time zone of this Date
  444.      *
  445.      * Sets the time zone of this date with the given
  446.      * Date_TimeZone object.  Does not alter the date/time,
  447.      * only assigns a new time zone.  For conversion, use
  448.      * convertTZ().
  449.      *
  450.      * @access public
  451.      * @param object Date_TimeZone $tz the Date_TimeZone object to use, if called 
  452.      * with a paramater that is not a Date_TimeZone object, will fall through to
  453.      * setTZbyID(). 
  454.      */
  455.     function setTZ($tz)
  456.     {
  457.         if(is_a($tz, 'Date_Timezone')) {
  458.             $this->tz = $tz;
  459.         } else {
  460.             $this->setTZbyID($tz);
  461.         }
  462.     }
  463.  
  464.     /**
  465.      * Sets the time zone of this date with the given time zone id
  466.      *
  467.      * Sets the time zone of this date with the given
  468.      * time zone id, or to the system default if the
  469.      * given id is invalid. Does not alter the date/time,
  470.      * only assigns a new time zone.  For conversion, use
  471.      * convertTZ().
  472.      *
  473.      * @access public
  474.      * @param string id a time zone id
  475.      */
  476.     function setTZbyID($id)
  477.     {
  478.         if (Date_TimeZone::isValidID($id)) {
  479.             $this->tz = new Date_TimeZone($id);
  480.         } else {
  481.             $this->tz = Date_TimeZone::getDefault();
  482.         }
  483.     }
  484.  
  485.     /**
  486.      * Tests if this date/time is in DST
  487.      *
  488.      * Returns true if daylight savings time is in effect for
  489.      * this date in this date's time zone.  See Date_TimeZone::inDaylightTime()
  490.      * for compatability information.
  491.      *
  492.      * @access public
  493.      * @return boolean true if DST is in effect for this date
  494.      */
  495.     function inDaylightTime()
  496.     {
  497.         return $this->tz->inDaylightTime($this);
  498.     }
  499.  
  500.     /**
  501.      * Converts this date to UTC and sets this date's timezone to UTC
  502.      *
  503.      * Converts this date to UTC and sets this date's timezone to UTC
  504.      *
  505.      * @access public
  506.      */
  507.     function toUTC()
  508.     {
  509.         if ($this->tz->getOffset($this) > 0) {
  510.             $this->subtractSeconds(intval($this->tz->getOffset($this) / 1000));
  511.         } else {
  512.             $this->addSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
  513.         }
  514.         $this->tz = new Date_TimeZone('UTC');
  515.     }
  516.  
  517.     /**
  518.      * Converts this date to a new time zone
  519.      *
  520.      * Converts this date to a new time zone.
  521.      * WARNING: This may not work correctly if your system does not allow
  522.      * putenv() or if localtime() does not work in your environment.  See
  523.      * Date::TimeZone::inDaylightTime() for more information.
  524.      *
  525.      * @access public
  526.      * @param object Date_TimeZone $tz the Date::TimeZone object for the conversion time zone
  527.      */
  528.     function convertTZ($tz)
  529.     {
  530.         // convert to UTC
  531.         if ($this->tz->getOffset($this) > 0) {
  532.             $this->subtractSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
  533.         } else {
  534.             $this->addSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
  535.         }
  536.         // convert UTC to new timezone
  537.         if ($tz->getOffset($this) > 0) {
  538.             $this->addSeconds(intval(abs($tz->getOffset($this)) / 1000));
  539.         } else {
  540.             $this->subtractSeconds(intval(abs($tz->getOffset($this)) / 1000));
  541.         }
  542.         $this->tz = $tz;
  543.     }
  544.  
  545.     /**
  546.      * Converts this date to a new time zone, given a valid time zone ID
  547.      *
  548.      * Converts this date to a new time zone, given a valid time zone ID
  549.      * WARNING: This may not work correctly if your system does not allow
  550.      * putenv() or if localtime() does not work in your environment.  See
  551.      * Date::TimeZone::inDaylightTime() for more information.
  552.      *
  553.      * @access public
  554.      * @param string id a time zone id
  555.      */
  556.     function convertTZbyID($id)
  557.     {
  558.        if (Date_TimeZone::isValidID($id)) {
  559.           $tz = new Date_TimeZone($id);
  560.        } else {
  561.           $tz = Date_TimeZone::getDefault();
  562.        }
  563.        $this->convertTZ($tz);
  564.     }
  565.  
  566.     function toUTCbyOffset($offset)
  567.     {
  568.         if ($offset == "Z" || $offset == "+00:00" || $offset == "+0000") {
  569.             $this->toUTC();
  570.             return true;
  571.         }
  572.  
  573.         if (preg_match('/([\+\-])(\d{2}):?(\d{2})/', $offset, $regs)) {
  574.             // convert offset to seconds
  575.             $hours  = (int) isset($regs[2])?$regs[2]:0;
  576.             $mins   = (int) isset($regs[3])?$regs[3]:0;
  577.             $offset = ($hours * 3600) + ($mins * 60);
  578.  
  579.             if (isset($regs[1]) && $regs[1] == "-") {
  580.                 $offset *= -1;
  581.             }
  582.  
  583.             if ($offset > 0) {
  584.                 $this->subtractSeconds(intval($offset));
  585.             } else {
  586.                 $this->addSeconds(intval(abs($offset)));
  587.             }
  588.  
  589.             $this->tz = new Date_TimeZone('UTC');
  590.             return true;
  591.         }
  592.  
  593.         return false;
  594.     }
  595.  
  596.     /**
  597.      * Adds a given number of seconds to the date
  598.      *
  599.      * Adds a given number of seconds to the date
  600.      *
  601.      * @access public
  602.      * @param int $sec the number of seconds to add
  603.      */
  604.     function addSeconds($sec)
  605.     {
  606.         $this->addSpan(new Date_Span((integer)$sec));
  607.     }
  608.  
  609.     /**
  610.      * Adds a time span to the date
  611.      *
  612.      * Adds a time span to the date
  613.      *
  614.      * @access public
  615.      * @param object Date_Span $span the time span to add
  616.      */
  617.     function addSpan($span)
  618.     {
  619.         if (!is_a($span, 'Date_Span')) {
  620.             return;
  621.         }
  622.  
  623.         $this->second += $span->second;
  624.         if ($this->second >= 60) {
  625.             $this->minute++;
  626.             $this->second -= 60;
  627.         }
  628.  
  629.         $this->minute += $span->minute;
  630.         if ($this->minute >= 60) {
  631.             $this->hour++;
  632.             if ($this->hour >= 24) {
  633.                 list($this->year, $this->month, $this->day) =
  634.                     sscanf(Date_Calc::nextDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  635.                 $this->hour -= 24;
  636.             }
  637.             $this->minute -= 60;
  638.         }
  639.  
  640.         $this->hour += $span->hour;
  641.         if ($this->hour >= 24) {
  642.             list($this->year, $this->month, $this->day) =
  643.                 sscanf(Date_Calc::nextDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  644.             $this->hour -= 24;
  645.         }
  646.  
  647.         $d = Date_Calc::dateToDays($this->day, $this->month, $this->year);
  648.         $d += $span->day;
  649.  
  650.         list($this->year, $this->month, $this->day) =
  651.             sscanf(Date_Calc::daysToDate($d), "%04s%02s%02s");
  652.         $this->year  = intval($this->year);
  653.         $this->month = intval($this->month);
  654.         $this->day   = intval($this->day);
  655.     }
  656.  
  657.     /**
  658.      * Subtracts a given number of seconds from the date
  659.      *
  660.      * Subtracts a given number of seconds from the date
  661.      *
  662.      * @access public
  663.      * @param int $sec the number of seconds to subtract
  664.      */
  665.     function subtractSeconds($sec)
  666.     {
  667.         $this->subtractSpan(new Date_Span($sec));
  668.     }
  669.  
  670.     /**
  671.      * Subtracts a time span to the date
  672.      *
  673.      * Subtracts a time span to the date
  674.      *
  675.      * @access public
  676.      * @param object Date_Span $span the time span to subtract
  677.      */
  678.     function subtractSpan($span)
  679.     {
  680.         if (!is_a($span, 'Date_Span')) {
  681.             return;
  682.         }
  683.         if ($span->isEmpty()) {
  684.             return;
  685.         }
  686.  
  687.         $this->second -= $span->second;
  688.         if ($this->second < 0) {
  689.             $this->minute--;
  690.             $this->second += 60;
  691.         }
  692.  
  693.         $this->minute -= $span->minute;
  694.         if ($this->minute < 0) {
  695.             $this->hour--;
  696.             if ($this->hour < 0) {
  697.                 list($this->year, $this->month, $this->day) =
  698.                     sscanf(Date_Calc::prevDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  699.                 $this->hour += 24;
  700.             }
  701.             $this->minute += 60;
  702.         }
  703.  
  704.         $this->hour -= $span->hour;
  705.         if ($this->hour < 0) {
  706.             list($this->year, $this->month, $this->day) =
  707.                 sscanf(Date_Calc::prevDay($this->day, $this->month, $this->year), "%04s%02s%02s");
  708.             $this->hour += 24;
  709.         }
  710.  
  711.         $d = Date_Calc::dateToDays($this->day, $this->month, $this->year);
  712.         $d -= $span->day;
  713.  
  714.         list($this->year, $this->month, $this->day) =
  715.             sscanf(Date_Calc::daysToDate($d), "%04s%02s%02s");
  716.         $this->year  = intval($this->year);
  717.         $this->month = intval($this->month);
  718.         $this->day   = intval($this->day);
  719.     }
  720.  
  721.     /**
  722.      * Compares two dates
  723.      *
  724.      * Compares two dates.  Suitable for use
  725.      * in sorting functions.
  726.      *
  727.      * @access public
  728.      * @param object Date $d1 the first date
  729.      * @param object Date $d2 the second date
  730.      * @return int 0 if the dates are equal, -1 if d1 is before d2, 1 if d1 is after d2
  731.      */
  732.     function compare($d1, $d2)
  733.     {
  734.         $d1->convertTZ(new Date_TimeZone('UTC'));
  735.         $d2->convertTZ(new Date_TimeZone('UTC'));
  736.         $days1 = Date_Calc::dateToDays($d1->day, $d1->month, $d1->year);
  737.         $days2 = Date_Calc::dateToDays($d2->day, $d2->month, $d2->year);
  738.         if ($days1 < $days2) return -1;
  739.         if ($days1 > $days2) return 1;
  740.         if ($d1->hour < $d2->hour) return -1;
  741.         if ($d1->hour > $d2->hour) return 1;
  742.         if ($d1->minute < $d2->minute) return -1;
  743.         if ($d1->minute > $d2->minute) return 1;
  744.         if ($d1->second < $d2->second) return -1;
  745.         if ($d1->second > $d2->second) return 1;
  746.         return 0;
  747.     }
  748.  
  749.     /**
  750.      * Test if this date/time is before a certain date/time
  751.      *
  752.      * Test if this date/time is before a certain date/time
  753.      *
  754.      * @access public
  755.      * @param object Date $when the date to test against
  756.      * @return boolean true if this date is before $when
  757.      */
  758.     function before($when)
  759.     {
  760.         if (Date::compare($this,$when) == -1) {
  761.             return true;
  762.         } else {
  763.             return false;
  764.         }
  765.     }
  766.  
  767.     /**
  768.      * Test if this date/time is after a certian date/time
  769.      *
  770.      * Test if this date/time is after a certian date/time
  771.      *
  772.      * @access public
  773.      * @param object Date $when the date to test against
  774.      * @return boolean true if this date is after $when
  775.      */
  776.     function after($when)
  777.     {
  778.         if (Date::compare($this,$when) == 1) {
  779.             return true;
  780.         } else {
  781.             return false;
  782.         }
  783.     }
  784.  
  785.     /**
  786.      * Test if this date/time is exactly equal to a certian date/time
  787.      *
  788.      * Test if this date/time is exactly equal to a certian date/time
  789.      *
  790.      * @access public
  791.      * @param object Date $when the date to test against
  792.      * @return boolean true if this date is exactly equal to $when
  793.      */
  794.     function equals($when)
  795.     {
  796.         if (Date::compare($this,$when) == 0) {
  797.             return true;
  798.         } else {
  799.             return false;
  800.         }
  801.     }
  802.  
  803.     /**
  804.      * Determine if this date is in the future
  805.      *
  806.      * Determine if this date is in the future
  807.      *
  808.      * @access public
  809.      * @return boolean true if this date is in the future
  810.      */
  811.     function isFuture()
  812.     {
  813.         $now = new Date();
  814.         if ($this->after($now)) {
  815.             return true;
  816.         } else {
  817.             return false;
  818.         }
  819.     }
  820.  
  821.     /**
  822.      * Determine if this date is in the past
  823.      *
  824.      * Determine if this date is in the past
  825.      *
  826.      * @access public
  827.      * @return boolean true if this date is in the past
  828.      */
  829.     function isPast()
  830.     {
  831.         $now = new Date();
  832.         if ($this->before($now)) {
  833.             return true;
  834.         } else {
  835.             return false;
  836.         }
  837.     }
  838.  
  839.     /**
  840.      * Determine if the year in this date is a leap year
  841.      *
  842.      * Determine if the year in this date is a leap year
  843.      *
  844.      * @access public
  845.      * @return boolean true if this year is a leap year
  846.      */
  847.     function isLeapYear()
  848.     {
  849.         return Date_Calc::isLeapYear($this->year);
  850.     }
  851.  
  852.     /**
  853.      * Get the Julian date for this date
  854.      *
  855.      * Get the Julian date for this date
  856.      *
  857.      * @access public
  858.      * @return int the Julian date
  859.      */
  860.     function getJulianDate()
  861.     {
  862.         return Date_Calc::julianDate($this->day, $this->month, $this->year);
  863.     }
  864.  
  865.     /**
  866.      * Gets the day of the week for this date
  867.      *
  868.      * Gets the day of the week for this date (0=Sunday)
  869.      *
  870.      * @access public
  871.      * @return int the day of the week (0=Sunday)
  872.      */
  873.     function getDayOfWeek()
  874.     {
  875.         return Date_Calc::dayOfWeek($this->day, $this->month, $this->year);
  876.     }
  877.  
  878.     /**
  879.      * Gets the week of the year for this date
  880.      *
  881.      * Gets the week of the year for this date
  882.      *
  883.      * @access public
  884.      * @return int the week of the year
  885.      */
  886.     function getWeekOfYear()
  887.     {
  888.         return Date_Calc::weekOfYear($this->day, $this->month, $this->year);
  889.     }
  890.  
  891.     /**
  892.      * Gets the quarter of the year for this date
  893.      *
  894.      * Gets the quarter of the year for this date
  895.      *
  896.      * @access public
  897.      * @return int the quarter of the year (1-4)
  898.      */
  899.     function getQuarterOfYear()
  900.     {
  901.         return Date_Calc::quarterOfYear($this->day, $this->month, $this->year);
  902.     }
  903.  
  904.     /**
  905.      * Gets number of days in the month for this date
  906.      *
  907.      * Gets number of days in the month for this date
  908.      *
  909.      * @access public
  910.      * @return int number of days in this month
  911.      */
  912.     function getDaysInMonth()
  913.     {
  914.         return Date_Calc::daysInMonth($this->month, $this->year);
  915.     }
  916.  
  917.     /**
  918.      * Gets the number of weeks in the month for this date
  919.      *
  920.      * Gets the number of weeks in the month for this date
  921.      *
  922.      * @access public
  923.      * @return int number of weeks in this month
  924.      */
  925.     function getWeeksInMonth()
  926.     {
  927.         return Date_Calc::weeksInMonth($this->month, $this->year);
  928.     }
  929.  
  930.     /**
  931.      * Gets the full name or abbriviated name of this weekday
  932.      *
  933.      * Gets the full name or abbriviated name of this weekday
  934.      *
  935.      * @access public
  936.      * @param boolean $abbr abbrivate the name
  937.      * @return string name of this day
  938.      */
  939.     function getDayName($abbr = false, $length = 3)
  940.     {
  941.         if ($abbr) {
  942.             return Date_Calc::getWeekdayAbbrname($this->day, $this->month, $this->year, $length);
  943.         } else {
  944.             return Date_Calc::getWeekdayFullname($this->day, $this->month, $this->year);
  945.         }
  946.     }
  947.  
  948.     /**
  949.      * Gets the full name or abbriviated name of this month
  950.      *
  951.      * Gets the full name or abbriviated name of this month
  952.      *
  953.      * @access public
  954.      * @param boolean $abbr abbrivate the name
  955.      * @return string name of this month
  956.      */
  957.     function getMonthName($abbr = false)
  958.     {
  959.         if ($abbr) {
  960.             return Date_Calc::getMonthAbbrname($this->month);
  961.         } else {
  962.             return Date_Calc::getMonthFullname($this->month);
  963.         }
  964.     }
  965.  
  966.     /**
  967.      * Get a Date object for the day after this one
  968.      *
  969.      * Get a Date object for the day after this one.
  970.      * The time of the returned Date object is the same as this time.
  971.      *
  972.      * @access public
  973.      * @return object Date Date representing the next day
  974.      */
  975.     function getNextDay()
  976.     {
  977.         $day = Date_Calc::nextDay($this->day, $this->month, $this->year, "%Y-%m-%d");
  978.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  979.         $newDate = new Date();
  980.         $newDate->setDate($date);
  981.         return $newDate;
  982.     }
  983.  
  984.     /**
  985.      * Get a Date object for the day before this one
  986.      *
  987.      * Get a Date object for the day before this one.
  988.      * The time of the returned Date object is the same as this time.
  989.      *
  990.      * @access public
  991.      * @return object Date Date representing the previous day
  992.      */
  993.     function getPrevDay()
  994.     {
  995.         $day = Date_Calc::prevDay($this->day, $this->month, $this->year, "%Y-%m-%d");
  996.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  997.         $newDate = new Date();
  998.         $newDate->setDate($date);
  999.         return $newDate;
  1000.     }
  1001.  
  1002.     /**
  1003.      * Get a Date object for the weekday after this one
  1004.      *
  1005.      * Get a Date object for the weekday after this one.
  1006.      * The time of the returned Date object is the same as this time.
  1007.      *
  1008.      * @access public
  1009.      * @return object Date Date representing the next weekday
  1010.      */
  1011.     function getNextWeekday()
  1012.     {
  1013.         $day = Date_Calc::nextWeekday($this->day, $this->month, $this->year, "%Y-%m-%d");
  1014.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  1015.         $newDate = new Date();
  1016.         $newDate->setDate($date);
  1017.         return $newDate;
  1018.     }
  1019.  
  1020.     /**
  1021.      * Get a Date object for the weekday before this one
  1022.      *
  1023.      * Get a Date object for the weekday before this one.
  1024.      * The time of the returned Date object is the same as this time.
  1025.      *
  1026.      * @access public
  1027.      * @return object Date Date representing the previous weekday
  1028.      */
  1029.     function getPrevWeekday()
  1030.     {
  1031.         $day = Date_Calc::prevWeekday($this->day, $this->month, $this->year, "%Y-%m-%d");
  1032.         $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
  1033.         $newDate = new Date();
  1034.         $newDate->setDate($date);
  1035.         return $newDate;
  1036.     }
  1037.  
  1038.  
  1039.     /**
  1040.      * Returns the year field of the date object
  1041.      *
  1042.      * Returns the year field of the date object
  1043.      *
  1044.      * @access public
  1045.      * @return int the year
  1046.      */
  1047.     function getYear()
  1048.     {
  1049.         return $this->year;
  1050.     }
  1051.  
  1052.     /**
  1053.      * Returns the month field of the date object
  1054.      *
  1055.      * Returns the month field of the date object
  1056.      *
  1057.      * @access public
  1058.      * @return int the month
  1059.      */
  1060.     function getMonth()
  1061.     {
  1062.         return $this->month;
  1063.     }
  1064.  
  1065.     /**
  1066.      * Returns the day field of the date object
  1067.      *
  1068.      * Returns the day field of the date object
  1069.      *
  1070.      * @access public
  1071.      * @return int the day
  1072.      */
  1073.     function getDay()
  1074.     {
  1075.         return (int)$this->day;
  1076.     }
  1077.  
  1078.     /**
  1079.      * Returns the hour field of the date object
  1080.      *
  1081.      * Returns the hour field of the date object
  1082.      *
  1083.      * @access public
  1084.      * @return int the hour
  1085.      */
  1086.     function getHour()
  1087.     {
  1088.         return $this->hour;
  1089.     }
  1090.  
  1091.     /**
  1092.      * Returns the minute field of the date object
  1093.      *
  1094.      * Returns the minute field of the date object
  1095.      *
  1096.      * @access public
  1097.      * @return int the minute
  1098.      */
  1099.     function getMinute()
  1100.     {
  1101.         return $this->minute;
  1102.     }
  1103.  
  1104.     /**
  1105.      * Returns the second field of the date object
  1106.      *
  1107.      * Returns the second field of the date object
  1108.      *
  1109.      * @access public
  1110.      * @return int the second
  1111.      */
  1112.     function getSecond()
  1113.     {
  1114.          return $this->second;
  1115.     }
  1116.  
  1117.     /**
  1118.      * Set the year field of the date object
  1119.      *
  1120.      * Set the year field of the date object, invalid years (not 0-9999) are set to 0.
  1121.      *
  1122.      * @access public
  1123.      * @param int $y the year
  1124.      */
  1125.     function setYear($y)
  1126.     {
  1127.         if ($y < 0 || $y > 9999) {
  1128.             $this->year = 0;
  1129.         } else {
  1130.             $this->year = $y;
  1131.         }
  1132.     }
  1133.  
  1134.     /**
  1135.      * Set the month field of the date object
  1136.      *
  1137.      * Set the month field of the date object, invalid months (not 1-12) are set to 1.
  1138.      *
  1139.      * @access public
  1140.      * @param int $m the month
  1141.      */
  1142.     function setMonth($m)
  1143.     {
  1144.         if ($m < 1 || $m > 12) {
  1145.             $this->month = 1;
  1146.         } else {
  1147.             $this->month = $m;
  1148.         }
  1149.     }
  1150.  
  1151.     /**
  1152.      * Set the day field of the date object
  1153.      *
  1154.      * Set the day field of the date object, invalid days (not 1-31) are set to 1.
  1155.      *
  1156.      * @access public
  1157.      * @param int $d the day
  1158.      */
  1159.     function setDay($d)
  1160.     {
  1161.         if ($d > 31 || $d < 1) {
  1162.             $this->day = 1;
  1163.         } else {
  1164.             $this->day = $d;
  1165.         }
  1166.     }
  1167.  
  1168.     /**
  1169.      * Set the hour field of the date object
  1170.      *
  1171.      * Set the hour field of the date object in 24-hour format.
  1172.      * Invalid hours (not 0-23) are set to 0.
  1173.      *
  1174.      * @access public
  1175.      * @param int $h the hour
  1176.      */
  1177.     function setHour($h)
  1178.     {
  1179.         if ($h > 23 || $h < 0) {
  1180.             $this->hour = 0;
  1181.         } else {
  1182.             $this->hour = $h;
  1183.         }
  1184.     }
  1185.  
  1186.     /**
  1187.      * Set the minute field of the date object
  1188.      *
  1189.      * Set the minute field of the date object, invalid minutes (not 0-59) are set to 0.
  1190.      *
  1191.      * @access public
  1192.      * @param int $m the minute
  1193.      */
  1194.     function setMinute($m)
  1195.     {
  1196.         if ($m > 59 || $m < 0) {
  1197.             $this->minute = 0;
  1198.         } else {
  1199.             $this->minute = $m;
  1200.         }
  1201.     }
  1202.  
  1203.     /**
  1204.      * Set the second field of the date object
  1205.      *
  1206.      * Set the second field of the date object, invalid seconds (not 0-59) are set to 0.
  1207.      *
  1208.      * @access public
  1209.      * @param int $s the second
  1210.      */
  1211.     function setSecond($s) {
  1212.         if ($s > 59 || $s < 0) {
  1213.             $this->second = 0;
  1214.         } else {
  1215.             $this->second = $s;
  1216.         }
  1217.     }
  1218.  
  1219. } // Date
  1220.  
  1221.  
  1222. //
  1223. // END
  1224. ?>
  1225.